package gui;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;

import maze.Barcode;
import maze.Coordinate;
import maze.Direction;
import maze.Maze;
import pacman.Game;
import robots.Ghost;
import robots.OwnGhost;
import robots.VirtualGhost;
import simulation.ColorMap;
import simulation.Simulator;


/**
 * Displays the real maze and the other robots on their real positions.
 * 
 *
 */
public class MainGui extends JPanel{
	private static final int FPS = 30;
	public static final int NUMBEROFGHOSTS = 4;
	BufferedImage sector;
	BufferedImage pacman;
	BufferedImage ghost1;
	BufferedImage ghost2;
	BufferedImage ghost3;
	BufferedImage ghost4;
	BufferedImage background;
	BufferedImage map;
	BufferedImage colormap;
	BufferedImage robot;
	BufferedImage blackScreen;
	BufferedImage robotrotated;
	BufferedImage fog;
	BufferedImage ultrasonic;
	
	BufferedImage mazeView = new BufferedImage(600, 600, BufferedImage.TYPE_INT_ARGB);
	BufferedImage frame = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
	BufferedImage[] ghostsImg;

	Game game;
	Maze maze;
	Timer timer;
	double xOffset = 0;
	double yOffset = 0;
	private ArrayList<Ghost> ghosts;
	GhostPanel panels[] = new GhostPanel[NUMBEROFGHOSTS];
	Simulator simulator;
	boolean drawColormap = false;
	Coordinate diff;
	private HashMap<String, BufferedImage> imgs = new HashMap<String, BufferedImage>();
	int originrot = 0;
	private boolean listener = false;
	
	public MainGui( Game game, Maze maze,Simulator simulation, boolean listener){
		this.game = game;
		this.maze = maze;
		
		this.simulator = simulation;
		setMinimumSize(new Dimension(800,600));
		setMaximumSize(new Dimension(1900,1080));
		setPreferredSize(new Dimension(800,600));
		setSize(getPreferredSize());
		OwnGhost origin = null;
		for (OwnGhost g : simulator.getGhostLocations().keySet()) {
			origin = g;
		}
		
		try{
			Coordinate loc = maze.getCoordinateOfLocation(simulator.getGhostLocations().get(origin));
		
		 diff = new Coordinate( loc.x-origin.getCoordinate().x, loc.y-origin.getCoordinate().y);
		 
		 originrot = origin.getRotation()-simulator.getGhostRotations().get(origin);
			originrot = positivemoduloint(originrot, 360);
			if(originrot >45 && originrot<=135) {
				originrot = 1;
			} else if(originrot >135  && originrot<=225) {
				originrot = 2;
			} else if(originrot >225 && originrot<=315) {
				originrot = 3;
			} else originrot=0;
		}catch(Exception e){}
		 
		loadImages();
		ghostsImg  = new BufferedImage[NUMBEROFGHOSTS];
		ghostsImg[0] = ghost1;
		ghostsImg[1] = ghost2;
		ghostsImg[2] = ghost3;
		ghostsImg[3] = ghost4;
		mazeView = drawMazeImage( maze.getRawData());
		
		ghosts = new ArrayList<Ghost>();
		updateGhosts();
		timer = new Timer(1000 / FPS, new ActionListener() {

			// timer to set when to draw the screen and update values
			@Override
			public void actionPerformed(ActionEvent arg0) {
				
				
					updateGhosts();
				
					draw();
				

				timer.restart();

			}

		

			
		});
		
		this.addMouseListener(new MouseListener() {

			@Override
			public void mouseClicked(MouseEvent click) {
				try{
				if (click.getX()> getSize().width/8*6)
				{
					int panelsize = getSize().height/4;
					if(click.getY()>0  * panelsize && click.getY()< 1 * panelsize)
					{
						if (panels[0] == null){
							panels[0] = new GhostPanel(ghosts.get(0), getGame(),ghost1);
							panels[0].setImgs(imgs);
						}
						else{
							if(panels[0].isShowing())
									panels[0].hideFrame();
								else
									panels[0].showFrame();
						}
					}
					
					if(click.getY()>1  * panelsize && click.getY()< 2 * panelsize)
					{
						if (panels[1] == null){
							panels[1] = new GhostPanel(ghosts.get(1), getGame(),ghost2);
							panels[1].setImgs(imgs);
						}
						else{
							if(panels[1].isShowing())
									panels[1].hideFrame();
								else
									panels[1].showFrame();
						}
					}
					
					if(click.getY()>2  * panelsize && click.getY()< 3 * panelsize)
					{
						if (panels[2] == null){
							panels[2] = new GhostPanel(ghosts.get(2), getGame(),ghost3);
							panels[2].setImgs(imgs);
						}
						else{
							if(panels[2].isShowing())
									panels[2].hideFrame();
								else
									panels[2].showFrame();
						}
					}
					
					if(click.getY()>3  * panelsize && click.getY()< 4 * panelsize)
					{
						if (panels[3] == null){
							panels[3] = new GhostPanel(ghosts.get(3), getGame(),ghost4);
							panels[3].setImgs(imgs);
						}
						else{
							if(panels[3].isShowing())
									panels[3].hideFrame();
								else
									panels[3].showFrame();
						}
					}
					
					
				}
				}catch(Exception e){}
			

			}

			@Override
			public void mouseEntered(MouseEvent arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void mouseExited(MouseEvent arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void mousePressed(MouseEvent arg0) {

			}

			@Override
			public void mouseReleased(MouseEvent arg0) {

			}
		});
		this.addMouseMotionListener(new MouseMotionListener() {
			int x = 0;
			int y = 0;
			boolean init = false;

			@Override
			public void mouseDragged(MouseEvent arg0) {
				if ((arg0.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == MouseEvent.BUTTON1_DOWN_MASK && arg0.getX()<getWidth()*6/8) {
					if (init) {
						xOffset += (x - arg0.getX()) / 40.0;
						yOffset += (y - arg0.getY()) / 40.0;
					}
					x = arg0.getX();
					y = arg0.getY();
					init = true;
				}
			}

			@Override
			public void mouseMoved(MouseEvent arg0) {
				if (arg0.getButton() == MouseEvent.NOBUTTON)
					init = false;
			}

		});
		ComponentFrame.showFrame("Gui", this);
		timer.start();
		KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
		manager.addKeyEventDispatcher(new MyDispatcher());
		this.listener = listener;
	//	startAllGhostPanels();
	}
	public Game getGame(){
		return game;
	}
	
	private void updateGhosts() {
		
//		for (Ghost g : game.getGhosts()) {
//			if (g== null)
//				System.out.println("null");
//		}
//		System.out.println(ghosts.size() + "game :" + game.getGhosts().length );
	 if (ghosts.size()<NUMBEROFGHOSTS && game.getGhosts().length > ghosts.size() )
	 {
		ghosts = new ArrayList<Ghost>();
		int i = 0;
		
		
		Ghost[] g = Sorting.sortGhosts(game.getGhosts());
		for (Ghost ghost : g) {
			if (ghost != null)
			{
				ghosts.add(ghost);
				imgs.put(ghost.getName(), ghostsImg[i]);
				i++;
			}
			
		}
		
		
		for (GhostPanel p : panels) {
			if (p != null)
				p.setImgs(imgs);
		}
	 }
	}
	
	
	
	/**
	 * draws the real map to an Image
	 * @param m
	 * 			The image to draw to
	 * @param mazeToDraw
	 * 			The maze to draw
	 */
	private BufferedImage drawMazeImage( char[][] mazeToDraw) {
		BufferedImage img = new BufferedImage((mazeToDraw.length-1)*40, (mazeToDraw.length-1)*40,  BufferedImage.TYPE_INT_ARGB);
		Graphics map = img.getGraphics();
		
		
		BufferedImage fogofwar = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
		Graphics fogfwar = fogofwar.getGraphics();

		
		for (int i = 0; i < mazeToDraw.length*40/300+1; i++) {
			for (int j = 0; j < mazeToDraw.length*40/300+1; j++){
				map.drawImage(background, i*300, j*300,(i+1)*300,(j+1)*300,0,0,350,350, null);
			}
		}
		
		
		// draw sectors

		for (int i = 0; i < mazeToDraw.length - 1; i++) {
			for (int j = 0; j < (mazeToDraw[1].length) / 2; j++) {
				double YStartPos = (i) * 40;
				double XStartPos = (j) * 40;
				map.drawImage(sector, (int) XStartPos, (int) YStartPos, null);
			}
		}

		// draw barcodes
		for (Barcode code : maze.getBarcodes()) {
			

			int x = code.getPosition().getX();
			int y = mazeToDraw.length -2 - code.getPosition().getY();

			char[] bcode = new char[code.getCode().length()];
			for (int i = 0; i < bcode.length; i++) {
				bcode[i] = code.getCode().charAt(i);
			}

			int dir = code.getDirection();
			//reverse if needed
			if (dir == 3 || dir == 2) {
				for(int i = 0; i<bcode.length/2; i++) {
					char temp = bcode[i];
					bcode[i] = bcode[bcode.length-1-i];
					bcode[bcode.length-1-i] = temp;
				}
			}
			
			if (dir == 1 || dir == 3)
				drawBarcode(map, x, y, bcode, true);
			else
				drawBarcode(map, x, y, bcode, false);

		}

		// draw walls
		map.setColor(new Color(90, 43, 0));
		int YStart = 0;// (int)(-yOff*40);
		int XStart = 0;// (int)(-xOff*40);

		for (int i = 0; i < mazeToDraw.length; i++) {
			for (int h = 0; h < mazeToDraw[1].length; h += 2) {
				if (mazeToDraw[(int) (i)][(int) (h)] == 1) {

					map.drawLine(h / 2 * 40 - 1 - XStart, (i - 1) * 40 - YStart, (h / 2) * 40 - 1 - XStart, (i + 1 - 1) * 40 - YStart);
					map.drawLine(h / 2 * 40 - XStart, (i - 1) * 40 - YStart, (h / 2) * 40 - XStart, (i + 1 - 1) * 40 - YStart);
					map.drawLine(h / 2 * 40 + 1 - XStart, (i - 1) * 40 - YStart, (h / 2) * 40 + 1 - XStart, (i + 1 - 1) * 40 - YStart);
				}
				if (mazeToDraw[(int) (i)][(int) (h)] == 0) {
					map.drawImage(fog, (((h / 2) * 40) - 20), ((i - 1) * 40 - YStart), null);

				}

			}
			for (int v = 0; v < mazeToDraw[1].length - 1; v += 2) {

				if (mazeToDraw[i][v + 1] == 1) {

					map.drawLine((v / 2) * 40, (i + 1 - 1) * 40 - 1, (v / 2 + 1) * 40, (i + 1 - 1) * 40 - 1);
					map.drawLine((v / 2) * 40, (i + 1 - 1) * 40, (v / 2 + 1) * 40, (i + 1 - 1) * 40);
					map.drawLine((v / 2) * 40, (i + 1 - 1) * 40 + 1, (v / 2 + 1) * 40, (i + 1 - 1) * 40 + 1);
				}
				if (mazeToDraw[i][v + 1] == 0) {
					map.drawImage(fog, (((v / 2) * 40)), (((i) * 40) - 20), null);

				}
			}
		}
		if(drawColormap){
		BufferedImage[][] cm = simulator.getColorMap().getTileMap();
		try{for (int i = 0; i < cm.length; i++) {
			for (int j = 0; j < cm.length; j++) {
				map.drawImage(cm[j][ cm.length - 1 - i], j * 40, i * 40, null);// colormap.getHeight()-((i+1)*40),null);

			}	
		}}catch(Exception e){System.out.println("fail colormap");}
		}
		
		fogfwar.dispose();
		map.dispose();
		return img;
	}
	
	private void drawBarcode(Graphics g, int x, int y, char[] code, boolean hor) {

		if (hor) {
			for (int i = 0; i < 2 * code.length; i += 2) {

				if (code[i / 2] == '0')
					g.setColor(new Color(0, 0, 0));
				else
					g.setColor(new Color(255, 255, 255));

				g.drawLine(x * 40, (y * 40) + code.length + 3 + i, (x + 1) * 40, (y * 40) + code.length + 3 + i);
				g.drawLine(x * 40, (y * 40) + code.length + 3 + i + 1, (x + 1) * 40, (y * 40) + code.length + 3 + i + 1);
			}

		} else {
			for (int i = 0; i < 2 * code.length; i += 2) {
				if (code[i / 2] == '0')
					g.setColor(new Color(0, 0, 0));
				else
					g.setColor(new Color(255, 255, 255));

				g.drawLine(x * 40 + code.length + i + 3, (y * 40), (x) * 40 + code.length + i + 3, ((y + 1) * 40));
				g.drawLine(x * 40 + code.length + i + 1 + 3, (y * 40), (x) * 40 + code.length + i + 1 + 3, ((y + 1) * 40));
			}
		}
	}
	
	private void drawPacman(Graphics map){
  
		
			
		double x = simulator.getPacmanLocation().x;
		double y = simulator.getPacmanLocation().y;
		
		y = (maze.getSize()*40)  - y;
		
		int angle = simulator.getPacmanRotation();
		map.drawImage(Graphic.rotate(pacman, angle), (int) ((x- xOffset*40) - pacman.getWidth()/2) , (int) ((y- yOffset*40) - pacman.getHeight()/2) , 40,40 ,null);
		}

	
	
	private void drawRobotsInSimualator(Graphics map){
		OwnGhost origin = null;
		for (OwnGhost bot : simulator.getGhostLocations().keySet()) {
			//System.out.println("draw ghost: " + bot.getName());
			double x = (simulator.getGhostLocations().get(bot).x / 40);
			double y = (simulator.getGhostLocations().get(bot).y / 40);
			
			int angle = simulator.getGhostRotations().get(bot);
			if (!((int) ((x - xOffset) * 40) >= 600)) {
			y = (maze.getSize())  - y;
		
				map.setColor(Color.GREEN);

				// draw robot in simulator
				BufferedImage rotatedbot = Graphic.scale(Graphic.rotate(robot, angle), 0.75);
				map.drawImage(rotatedbot, (int) ((x - xOffset) * 40) - rotatedbot.getWidth() / 2, (int) ((y - yOffset) * 40) - rotatedbot.getHeight() / 2, null);
				map.drawString("Ghost-" + bot.getName(), (int) ((x - xOffset) * 40) - 20, (int) ((y - yOffset) * 40) - 20);

			}
			origin = bot;
		}
		
		
		
		
		for (Ghost g : ghosts) {
		
			//if (!simulator.getGhostLocations().keySet().contains(g)){
				try{
				//if (origin.alreadyMatchedMaze(g.getMaze())){
					if (!g.equals(origin) && !(g instanceof OwnGhost) && origin.alreadyMatchedGhost(g)){
					//Coordinate bDiff = getDifferenceBarcodes(origin.getMaze(), g.getMaze());
					Coordinate temppre = new Coordinate(0,0);
					temppre.x = game.getGhostPositions().get(g).x;
					temppre.y = game.getGhostPositions().get(g).y;
					Coordinate temp = origin.getMazeOnName(g.getName()).reverseTransform(temppre);
//					int x = diff.x + origin.getCoordinate().x ;//+ bDiff.x;
//					int y = diff.y + origin.getCoordinate().y ;//+ bDiff.y;
					//int x = diff.x + game.getGhostPositions().get(g).x +bDiff.x;
					//int y = diff.y + game.getGhostPositions().get(g).y + bDiff.y;
					for(int i=0; i<originrot; i++) {
						int tijdelijk = temp.x;
						temp.x = temp.y;
						temp.y = -tijdelijk;
					}
					int x = diff.x + temp.x;
					int y = diff.y + temp.y;
					//x = (int) positivemodulo(x, maze.getMaxX()-maze.getMinX()+1);
					//y = (int) positivemodulo(y, (maze.getSize()+1));
					
					y = maze.getSize() -1 - y;
					map.drawString(g.getName(), (int) ((x - xOffset) * 40 + 30) , (int) ((y - yOffset) * 40 +30)-30);
					map.drawImage(imgs.get(g.getName()), (int) ((x - xOffset) * 40) , (int) ((y - yOffset) * 40),40,40, null);
					}
				//}
				}catch(Exception e){}
			//}
		}
		
	}
	
	private double positivemodulo(double val, double mod) {
		mod = Math.abs(mod); // no negative modulo allowed
		mod = (mod == 0) ? 1 : mod; // no zero modulo either
		while (val < 0)
			val += mod; // increase val until we're sure it's positive
		return val % mod;
	}
	
	private int positivemoduloint(int val, int mod) {
		mod = Math.abs(mod); // no negative modulo allowed
		mod = (mod == 0) ? 1 : mod; // no zero modulo either
		while (val < 0)
			val += mod; // increase val until we're sure it's positive
		return val % mod;
	}
	
	/**
	 * returns the difference in position of the barcode according to own coordinates in maze
	 * @return
	 */
	private Coordinate getDifferenceBarcodes(Maze orig, Maze other){
		for (Barcode b : other.getBarcodes()) {
			for (Barcode b2 : orig.getBarcodes()) {
				if (b.equals(b2)) {
					return new Coordinate(b2.getX()-b.getX(), b2.getY()-b.getY());
				}
			}
		}
		return null;
	}
	
	private void draw() {
		Graphics g = frame.getGraphics();
		g.setColor(Color.GRAY);
		g.fillRect(0, 0, 600, 600);
		g.drawImage(mazeView, 0, 0, 600, 600, (int) (0 + 40 * xOffset), (int) (0 + 40 * yOffset), 600 + (int) (40 * xOffset), 600 + (int) (40 * yOffset), null);
		drawPacman(g);
		drawRobotsInSimualator(g);
		g.setColor(new Color(255, 160, 0));
		
		
		
		for (int i = 0; i < 4; i++) {
			
		
			g.drawImage(blackScreen,600,i*150,200,150,null);
			try{
				g.drawString(ghosts.get(i).getName() , 640,i*150+15);
			g.drawImage(ghostsImg[i],640,i*150+15,100,100,null);
			}catch(Exception e){}
			try{
				
				if (((OwnGhost)ghosts.get(i)).getCurrentStrategy() == null)
					g.drawString(ghosts.get(i).getName() + ": " + "Gewonnen!", 640,i*150+15);
				else
					g.drawString(ghosts.get(i).getName() + ": " + ((OwnGhost)ghosts.get(i)).getCurrentStrategy() , 640,i*150+15);
//				g.drawString("light: " +  ((OwnGhost)ghosts.get(i)).getLightSensor().readValue() , 605,i*150+45);
				}catch(Exception e){}
		}
		
		g.dispose();
		repaint();
	}
	
	@Override
	public void paint(Graphics g){
		
		g.drawImage(frame,0,0,getSize().width,getSize().height,null);
		
	}
	
	@Override
	public void update(Graphics g){
		paint(g);
	}
	
	/**
	 * Loads the images used
	 */
	public void loadImages() {
		try {
			sector = ImageIO.read(new File("./gui/sector_rand.png"));
			pacman = ImageIO.read(new File("./gui/pacman.png"));
			background = ImageIO.read(new File("./gui/wood.jpg"));
			robot = ImageIO.read(new File("./gui/robot.png"));
			blackScreen = ImageIO.read(new File("./gui/DataScreenRobot.png"));
			robotrotated = ImageIO.read(new File("./gui/robot.png"));
			fog = ImageIO.read(new File("./gui/fogofwar.png"));
			ultrasonic = ImageIO.read(new File("gui/ultrasonic.png"));
			ghost1 = ImageIO.read(new File("./gui/ghost_120.png"));
			ghost2 = ImageIO.read(new File("./gui/ghost_210.png"));
			ghost3 = ImageIO.read(new File("./gui/ghost_30.png"));
			ghost4 = ImageIO.read(new File("./gui/ghost_300.png"));

		} catch (IOException ex) {
			try {
				sector = ImageIO.read(new File("..\\PenOGuiFiles\\sector_rand.png"));
				pacman = ImageIO.read(new File("..\\PenOGuiFiles\\pacman.png"));
				background = ImageIO.read(new File("..\\PenOGuiFiles\\wood.jpg"));
				robot = ImageIO.read(new File("..\\PenOGuiFiles\\robot.png"));
				blackScreen = ImageIO.read(new File("..\\PenOGuiFiles\\DataScreenRobot.png"));
				robotrotated = ImageIO.read(new File("..\\PenOGuiFiles\\robot.png"));
				ghost1 = ImageIO.read(new File("..\\PenOGuiFiles\\ghost_120.png"));
				ghost2 = ImageIO.read(new File("..\\PenOGuiFiles\\ghost_210.png"));
				ghost3 = ImageIO.read(new File("..\\PenOGuiFiles\\ghost_30.png"));
				ghost4 = ImageIO.read(new File("..\\PenOGuiFiles\\ghost_300.png"));
			} catch (IOException e) {
				try {
					sector = ImageIO.read(new File("../PenOTiles/sector_rand.png"));
					pacman = ImageIO.read(new File("../PenOTiles/pacman.png"));
					background = ImageIO.read(new File("../PenOTiles/wood.jpg"));
					robot = ImageIO.read(new File("../PenOTiles/robot.png"));
					blackScreen = ImageIO.read(new File("../PenOTiles/DataScreenRobot.png"));
					robotrotated = ImageIO.read(new File("../PenOTiles/robot.png"));
					fog = ImageIO.read(new File("../PenOTiles/fogofwar.png"));
					ultrasonic = ImageIO.read(new File("../PenOTiles/ultrasonic.png"));
					ghost1 = ImageIO.read(new File("../PenOTiles/ghost_120.png"));
					ghost2 = ImageIO.read(new File("../PenOTiles/ghost_210.png"));
					ghost3 = ImageIO.read(new File("../PenOTiles/ghost_30.png"));
					ghost4 = ImageIO.read(new File("../PenOTiles/ghost_300.png"));
				} catch (IOException e1) {
					System.out.println("file not found in GuiTest");
			
				}

			}
		}
		
	}
	
	
	
	public static void main(String args[]) throws IOException{
		char[][] walls = { // index with maze[-y][x]
				{ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 },
						{ 1, 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 1 },
						{ 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1 },
						{ 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1 },
						{ 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1 },
						{ 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1 },
						{ 1, 2, 1, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 1 },
						{ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1 },
						{ 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1 },
						{ 1, 2, 1, 2, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
						{ 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1 },
						{ 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
						{ 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
						{ 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1 },
						{ 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1 },
						{ 1, 2, 2, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1 },
						{ 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1 },
						{ 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1 },
						{ 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
						{ 1, 2, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1, 2, 1 },
						{ 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1 } };
				Maze maze = new Maze(walls);
				maze.addBarcode(new Coordinate(2, 3), "1011000", 0);
		ColorMap c = new ColorMap();
		c.setupMap(maze, maze.getSize(), maze.getSize());
		Game game = new Game();
		OwnGhost ghostt = new VirtualGhost(game,"Jos",new Simulator(maze, c));
		Ghost ghostt2 = new Ghost(new Coordinate(0,0),game,"Jef");
		Ghost ghostt3 = new Ghost(new Coordinate(0,0),game,"Jan");
		Ghost ghostt4 = new Ghost(new Coordinate(0,0),game,"Joske");
		
		Ghost[] ghosts = {ghostt,ghostt2,ghostt3,ghostt4};
		game.setGhosts(ghosts);
		game.getPacman().setCoordinate(new Coordinate(2, 2));
		MainGui gui = new MainGui(game, maze,null,false);
	}
	
	private class MyDispatcher implements KeyEventDispatcher {
		@Override
		public boolean dispatchKeyEvent(KeyEvent e) {
			if (listener){
		 if (e.getID() == KeyEvent.KEY_RELEASED) {
			 
				int keyCode = e.getKeyCode();
				switch (keyCode) 
				{
				//used to move pacman in the gui
				case KeyEvent.VK_ENTER:
					drawColormap = !drawColormap;
					mazeView = drawMazeImage(maze.getRawData());
					break;		
				case KeyEvent.VK_UP:
					simulator.getPacmanPilot().stop();
					break;	
				case KeyEvent.VK_DOWN:
					simulator.getPacmanPilot().stop();
					break;	
				case KeyEvent.VK_LEFT:
					simulator.getPacmanPilot().stop();
					break;	
				case KeyEvent.VK_RIGHT:
					simulator.getPacmanPilot().stop();
					break;	
				}
				
			
		}
		 if (e.getID() == KeyEvent.KEY_PRESSED) {

				int keyCode = e.getKeyCode();
				Coordinate c;
				switch (keyCode) 
				{
				//used to move pacman in the gui
					
				case KeyEvent.VK_UP:
					simulator.getPacmanPilot().startTravel(true);
					break;	
				case KeyEvent.VK_DOWN:
					simulator.getPacmanPilot().startTravel(false);
					break;	
				case KeyEvent.VK_LEFT:
					simulator.getPacmanPilot().startRotate(false);
					break;	
				case KeyEvent.VK_RIGHT:
					simulator.getPacmanPilot().startRotate(true);
					break;	
				
				case KeyEvent.VK_NUMPAD2:
					 c = simulator.getPacman().getCoordinate();
					if (c.y >0){
						if (maze.read(c.x ,c.y,Direction.SOUTH,true) == 2)
						simulator.getPacman().setCoordinate(new Coordinate(c.x, c.y -1));	
					}
						break;
				case KeyEvent.VK_NUMPAD8:
					c = simulator.getPacman().getCoordinate();
					if (c.y <maze.getSize()-1){
						if (maze.read(c.x ,c.y,Direction.NORTH,true) == 2)
						simulator.getPacman().setCoordinate(new Coordinate(c.x, c.y +1));	
					}
						break;
				case KeyEvent.VK_NUMPAD4:
					c = simulator.getPacman().getCoordinate();
					if (c.x > 0){
						if (maze.read(c.x ,c.y,Direction.WEST,true) == 2)
						simulator.getPacman().setCoordinate(new Coordinate(c.x-1, c.y ));	
					}
						break;		
				case KeyEvent.VK_NUMPAD6:
					c = simulator.getPacman().getCoordinate();
					if (c.x <maze.getSize()-1){
						if (maze.read(c.x ,c.y,Direction.EAST,true) == 2)
						simulator.getPacman().setCoordinate(new Coordinate(c.x+1, c.y ));	
					}
						break;		
				}
				
		}
		 
			
			return false;
		}
			return false;
			
	}
	}
}
